<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <p data-lake-id="u190f90ee" id="u190f90ee"><span data-lake-id="u57cfaba5" id="u57cfaba5">如何基于这个分表字段来准确的把数据分表到某一张表中？</span></p>
  <p data-lake-id="u19407ce2" id="u19407ce2"><br></p>
  <p data-lake-id="u13301643" id="u13301643"><span data-lake-id="u77db9d09" id="u77db9d09">这就是分表算法要做的事情了，</span><strong><span data-lake-id="u090c1236" id="u090c1236">但是不管什么算法，我们都需要确保一个前提，那就是同一个分表字段，经过这个算法处理后，得到的结果一定是一致的，不可变的。</span></strong></p>
  <p data-lake-id="u28564acd" id="u28564acd"><br></p>
  <p data-lake-id="uea3090f1" id="uea3090f1"><span data-lake-id="u6cc695dd" id="u6cc695dd">通常情况下，当我们对order表进行分表的时候，比如我们要分成128张表的话，那么得到的128表应该是:order_0000、order_0001、order_0002.....order_0126、order_0127</span></p>
  <p data-lake-id="u80d40cba" id="u80d40cba"><br></p>
  <p data-lake-id="ua88a76de" id="ua88a76de"><span data-lake-id="uc8aba79c" id="uc8aba79c">通常的分表算法有以下几种：</span></p>
  <p data-lake-id="ud58a471e" id="ud58a471e"><br></p>
  <h3 data-lake-id="pMyP6" id="pMyP6"><span data-lake-id="u944d4207" id="u944d4207">直接取模</span></h3>
  <p data-lake-id="u002909bc" id="u002909bc"><br></p>
  <p data-lake-id="u681f8c4d" id="u681f8c4d"><span data-lake-id="u7e6f36da" id="u7e6f36da">在分库分表时，我们是事先可以知道要分成多少个库和多少张表的，所以，比较简单的就是取模的方式。</span></p>
  <p data-lake-id="ub05739c8" id="ub05739c8"><br></p>
  <p data-lake-id="uf375241a" id="uf375241a"><span data-lake-id="u4b6d713e" id="u4b6d713e">比如我们要分成128张表的话，就用一个整数来对128取模就行了，得到的结果如果是0002，那么就把数据放到order_0002这张表中。</span></p>
  <p data-lake-id="u38519f7f" id="u38519f7f"><span data-lake-id="u6bc96159" id="u6bc96159">​</span><br></p>
  <h3 data-lake-id="WcJd3" id="WcJd3"><span data-lake-id="ua2f11f51" id="ua2f11f51">按照关键字</span></h3>
  <p data-lake-id="udb0e8d87" id="udb0e8d87"><br></p>
  <p data-lake-id="u1f1160eb" id="u1f1160eb"><span data-lake-id="uc1a0a82f" id="uc1a0a82f">有的时候，我们在分表的时候，可以给予一定的关键字做拆分，比如按照时间，比如某个月份或者年份的数据单独放在某一个表中，或者可以按照地区分表也比较常见。</span></p>
  <p data-lake-id="uaeab12f5" id="uaeab12f5"><br></p>
  <h3 data-lake-id="YDnNU" id="YDnNU"><span data-lake-id="u03aa1528" id="u03aa1528">Hash取模</span></h3>
  <p data-lake-id="ue38783ae" id="ue38783ae"><br></p>
  <p data-lake-id="u49140a4f" id="u49140a4f"><span data-lake-id="u14a270ff" id="u14a270ff">那如果分表字段不是数字类型，而是字符串类型怎么办呢？有一个办法就是哈希取模，就是先对这个分表字段取Hash，然后在再取模。</span></p>
  <p data-lake-id="uc01fc45e" id="uc01fc45e"><br></p>
  <p data-lake-id="u124866e9" id="u124866e9"><span data-lake-id="uc79c54da" id="uc79c54da">但是需要注意的是，</span><strong><span data-lake-id="u64d5eab7" id="u64d5eab7">Java中的hash方法得到的结果有可能是负数</span></strong><span data-lake-id="u24cd66a4" id="u24cd66a4">，需要考虑这种负数的情况。</span></p>
  <p data-lake-id="ue73bf875" id="ue73bf875"><br></p>
  <h3 data-lake-id="FSDny" id="FSDny"><span data-lake-id="uc022cfd4" id="uc022cfd4">一致性Hash</span></h3>
  <p data-lake-id="ufb1228ac" id="ufb1228ac"><br></p>
  <p data-lake-id="u920c9aad" id="u920c9aad"><span data-lake-id="uf59af502" id="uf59af502">前面两种取模方式都比较不错，可以使我们的数据比较均匀的分布到多张分表中。但是还是存在一个缺点。</span></p>
  <p data-lake-id="u5b2da55b" id="u5b2da55b"><br></p>
  <p data-lake-id="ufdb8c471" id="ufdb8c471"><span data-lake-id="u0cc863d4" id="u0cc863d4">那就是如果需要扩容二次分表，表的总数量发生变化时，就需要重新计算hash值，就需要涉及到数据迁移了。</span></p>
  <p data-lake-id="u8cbc4449" id="u8cbc4449"><br></p>
  <p data-lake-id="u0cb90d1e" id="u0cb90d1e"><span data-lake-id="udad16d43" id="udad16d43">为了解决扩容的问题，我们可以采用一致性哈希的方式来做分表。</span></p>
  <p data-lake-id="u7b6038e0" id="u7b6038e0"><br></p>
  <p data-lake-id="ub5082667" id="ub5082667"><br></p>
  <p data-lake-id="u3f610dfb" id="u3f610dfb"><strong><span data-lake-id="u0b67aebc" id="u0b67aebc">一致性哈希可以按照常用的hash算法来将对应的key哈希到一个具有2^32次方个节点的空间中，形成成一个顺时针首尾相接的闭合的环形。所以当添加一台新的数据库服务器时，只有增加服务器的位置和逆时针方向第一台服务器之间的键会受影响。</span></strong></p>
 </body>
</html>